<template>
  <transition name="fade">
    <dl
      ref="messOpeMenuRef"
      class="opearMenu"
      v-if="modelValue"
      v-outClose="handleToShow"
    >
      <dt @click="openDialog('确定删除该条消息？')">删除</dt>
      <dt
        v-if="
          messageData?.userId === user.userId &&
          messageData.time &&
          currentTime - messageData.time <= 300000
        "
        @click="withdraw"
      >
        撤回
      </dt>
      <dt @click="startMultiple">多选</dt>
      <dt v-if="messageData?.type === 'text'" @click="copy" id="copy">复制</dt>
      <dt @click="forward" v-if="!messageData?.isError === true">转发</dt>
      <dt
        v-if="messageData?.type === 'voice'"
        @click="download(messageData?.type as any)"
      >
        下载
      </dt>
    </dl></transition
  >
  <confirm-dialog
    to=".chat-box"
    v-model="showDialog"
    width="35%"
    title="删除消息"
    :isLoading="isLoading"
    @confirm="deleteMessage"
  >
    <p>{{ deleText }}</p>
  </confirm-dialog>
  <teleport to="#chat-col__messages">
    <el-collapse-transition>
      <div class="delete-box clearfix" v-if="showDeleBox">
        <SvgIcon icon-class="close" popper-class="deleteIcon" @click="closeMultiple" />
        <span class="delete-box__desc">已选择 {{ selectIds.size }} 条消息</span>
        <el-button
          class="button-delete"
          type="danger"
          :disabled="!selectIds.size"
          plain
          @click="openDialog(`确定删除该${selectIds.size}条消息？`)"
          >删除</el-button
        >
        <el-button
          class="button-forward"
          type="primary"
          :disabled="!selectIds.size"
          plain
          @click="forward"
          >转发</el-button
        >
      </div>
    </el-collapse-transition></teleport
  >
  <sele-friend
    v-model="isForward"
    @confirm="startForwardMess"
    :is-loading="isLoading"
  ></sele-friend>
</template>

<script lang="ts" setup>
import { ref, watch, nextTick } from "vue";
import vOutClose from "@/directives/vueClickClose";
import { useMessagePinia } from "@/pinia/messages";
import { useUserPinia } from "@/pinia/user";
import { storeToRefs } from "pinia";
import { ElMessage } from "element-plus";
import confirmDialog from "@/components/confirmDialog.vue";
import Clipboard from "clipboard";
import seleFriend from "@/components/seleFriend.vue";
import { replaceEmotion } from "@/directives/filterText";
import { saveAs } from "file-saver";

const props = withDefaults(
  defineProps<{
    modelValue: boolean;
    messageId?: string;
    messageData?: Message;
    // 对方的userId值
    otherId: string;
    showSelect: boolean;
    // 当前用户所选的信息的id值集合
    selectIds: Set<string>;
  }>(),
  {
    messageId: "",
  }
);
const emits = defineEmits<{
  (e: "update:modelValue", show: boolean): void;
  (e: "update:showSelect", show: boolean): void;
}>();

const messageStore = useMessagePinia();
const { user } = storeToRefs(useUserPinia());

/**
 * 改变该组件的显示状态
 */
const handleToShow: (show: boolean) => void = (show: boolean): void => {
  emits("update:modelValue", show);
};

/**
 * 当前标准时间的时间戳
 */
const currentTime = ref<number>(new Date().getTime());
const timing = ref();

watch(
  () => props.messageId,
  (newValue) => {
    if (newValue) {
      currentTime.value = new Date().getTime();
      if (currentTime.value - props.messageData!.time! <= 300000)
        timing.value = setInterval(() => {
          currentTime.value = new Date().getTime();
          if (currentTime.value - props.messageData!.time! > 300000)
            clearInterval(timing.value);
        }, 1000);
    } else if (timing.value) clearInterval(timing.value);
  }
);

// 多选时是否显示删除按钮
const showDeleBox = ref<boolean>(false);

// 准备多选
const startMultiple = () => {
  emits("update:modelValue", false);
  emits("update:showSelect", true);
  showDeleBox.value = true;
};

// 关闭多选操作
const closeMultiple = () => {
  props.selectIds.clear();
  emits("update:showSelect", false);
  nextTick(() => {
    showDeleBox.value = false;
  });
};

/**
 * 删除消息的提示文本
 */
const deleText = ref<string>("");
/**
 * 是否显示确认操作的对话框
 */
const showDialog = ref<boolean>(false);
/**
 * 是否正在删除该条消息
 */
const isLoading = ref<boolean>(false);

// 准备打开对话框
const openDialog = (text: string) => {
  if (props.modelValue) emits("update:modelValue", false);
  deleText.value = text;
  showDialog.value = true;
};

// 删除信息
const deleteMessage = () => {
  const ids: string[] = [...props.selectIds];
  if (
    ids.find((id: string) => id.startsWith("001")) ||
    (!ids.length && props.messageId.startsWith("001"))
  ) {
    isLoading.value = true;
    messageStore
      .deleteMessage(props.otherId, {
        selfId: user.value.userId,
        otherId: props.otherId,
        messageId: ids.length ? ids : [props.messageId],
      })
      .then((code: number) => {
        isLoading.value = false;
        showDialog.value = false;
        if (code === 1) {
          if (showDeleBox.value) closeMultiple();
        } else if (code === -2)
          ElMessage({
            type: "error",
            duration: 1500,
            message: "删除失败，对方和自己不是好友关系",
          });
        else
          ElMessage({
            type: "error",
            message: "删除失败",
            duration: 1500,
          });
      })
      .catch(() => {
        isLoading.value = false;
        showDialog.value = false;
        ElMessage({
          type: "error",
          message: "删除失败",
          duration: 1500,
        });
      });
  } else {
    const data = messageStore.chatList.get(props.otherId);
    if (ids.length) ids.forEach((id) => data?.messagesDatas.delete(id));
    else data?.messagesDatas.delete(props.messageId);
    showDialog.value = false;
    if (showDeleBox.value) closeMultiple();
  }
};

// 撤回某条消息
const withdraw = () => {
  props.messageData!.isLoading = true;
  emits("update:modelValue", false);
  messageStore
    .withdrawMessage({
      selfId: user.value.userId,
      otherId: props.otherId,
      messageId: props.messageId!,
    })
    .then((code: number) => {
      props.messageData!.isLoading = false;
      if (code === -2)
        ElMessage({
          type: "error",
          duration: 1500,
          message: "撤回失败，对方和自己不是好友关系",
        });
      else if (code !== 1) {
        ElMessage({
          type: "error",
          message: "撤回失败",
          duration: 1500,
        });
      }
    })
    .catch(() => {
      props.messageData!.isLoading = false;
      ElMessage({
        type: "error",
        message: "撤回失败",
        duration: 1500,
      });
    });
};

// 一键复制文本(包含图片)
const copy = () => {
  emits("update:modelValue", false);
  const content: string = props.messageData?.message ?? "";
  const clipboard = new Clipboard("#copy", {
    text: () => replaceEmotion(content, "chat-edit__emotion"),
  });
  clipboard.on("success", () => clipboard.destroy());
  clipboard.on("error", () => {
    ElMessage({
      type: "error",
      message: "复制失败",
      duration: 1500,
    });
    clipboard.destroy();
  });
};

/**
 * 是否需要转发消息
 */
const isForward = ref<boolean>(false);

// 转发消息打开对话框
const forward = () => {
  emits("update:modelValue", false);
  isForward.value = true;
};

// 开始转发消息操作
const startForwardMess = (selfId: string, otherIds: Array<string>) => {
  isLoading.value = true;
  const ids = [...props.selectIds];
  messageStore
    .forwardMessage({
      selfId,
      otherIds,
      messagesIds: ids.length ? ids : [props.messageId],
    })
    .then((code) => {
      isLoading.value = false;
      if (code === 1) {
        isForward.value = false;
        if (showDeleBox.value) closeMultiple();
      } else
        ElMessage({
          type: "error",
          message: "转发失败",
          duration: 1500,
        });
    })
    .catch(() => {
      isLoading.value = false;
      ElMessage({
        type: "error",
        message: "转发失败",
        duration: 1500,
      });
    });
};

// 下载音频或者文件
const download = (type: "voice") => {
  emits("update:modelValue", false);
  try {
    switch (type) {
      case "voice": {
        const url = props.messageData?.message;
        url && saveAs(url);
        break;
      }
    }
  } catch (error) {
    console.log(error);
    ElMessage({
      type: "error",
      message: "下载失败",
      duration: 1500,
    });
  }
};
</script>

<style lang="scss" scoped>
.fade {
  @include fade(0.15s, ease);
}

.opearMenu {
  @include opearMenu(999, 14px);
}

.delete-box {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background-color: #fff;
  padding: 0 20px;
  height: 50px;
  line-height: 50px;
  box: {
    sizing: border-box;
    shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.16);
  }
  color: #333;

  .deleteIcon {
    font-size: 18px;
    cursor: pointer;
    vertical-align: middle;
    transition: color 0.15s;

    &:hover {
      color: #79bbff;
    }
  }

  &__desc {
    margin-left: 20px;
    font-size: 13px;
  }

  .button {
    @mixin thame($right) {
      width: 60px;
      position: absolute;
      right: $right;
      top: 50%;
      transform: translateY(-50%);
    }

    &-delete {
      @include thame(20px);
    }

    &-forward {
      @include thame(100px);
    }
  }
}
</style>
